
local logger = {}

logger.DEBUG = 10
logger.INFO = 20
logger.WARNING = 30
logger.ERROR = 40

logger.log_level = logger.DEBUG
logger.stack_level = 3
logger.enable_log_src = true

--是否允许把错误发送到邮件
logger.enable_to_mail = false

logger.print = function(msg) return print(msg) end

-- get log stack
local function get_log_stack(log_level)
	local info = debug.getinfo(log_level + 1, "Sl")
	local src = info.source
	return src .. ":" .. info.currentline
end

-- log format
local function log_format(log_level, ...)
	local t = {...}
	local out = nil
	for _, v in pairs(t) do
		v_str = tostring(v)
		
		if not out then
			out = v_str
		else
			out = out .. "\t" .. v_str
		end
	end
	return out
end

-- log level name
local g_logger_names = {
	[logger.DEBUG] = "DEBUG",
	[logger.INFO] = "INFO",
	[logger.WARNING] = "WARN",
	[logger.ERROR] = "ERROR",
}
local function get_log_name(log_level)
	return g_logger_names[log_level]
end

-- to time string
local function log_timestamp(timestamp)
	local f = os.date("%Y-%m-%d %H:%M:%S", math.floor(timestamp))
	return f
end

-- send mail
local function send_mail(msg, time)
	-- local cmd = "echo " .. msg .. " | mail -s 'Error at " .. time .. "' dozen5609@163.com"
	-- print(cmd)
	-- os.execute(cmd)
end

-- log print
local function log_print(log_level, stack_level, ...)
	if log_level < logger.log_level then
		return
	end
	
	local timestamp = log_timestamp(os.time())
	local src = logger.enable_log_src and get_log_stack(stack_level) or ""
	local msg = log_format(log_level, ...)
	local log = string.format("%s %s %s :\n%s", get_log_name(log_level), timestamp, src, msg)
	
	if log_level == logger.ERROR and logger.enable_to_mail then
		send_mail(log, timestamp)
	end
	logger.print(log)	
end

-- write
function logger.write(log_level, stack_level, ...)
	log_print(log_level, stack_level or logger.stack_level, ...)
end

function logger.debug(...)
	log_print(logger.DEBUG, logger.stack_level, ...)
end
function logger.debugf(format, ...)
	log_print(logger.DEBUG, logger.stack_level, string.format(format, ...))
end

function logger.info(...)
	log_print(logger.INFO, logger.stack_level, ...)
end
function logger.infof(format, ...)
	log_print(logger.INFO, logger.stack_level, string.format(format, ...))
end

function logger.warn(...)
	log_print(logger.WARN, logger.stack_level, ...)
end
function logger.warnf(format, ...)
	log_print(logger.WARN, logger.stack_level, string.format(format, ...))
end

function logger.error(...)
	log_print(logger.ERROR, logger.stack_level, ...)
end

function logger.errorf(...)
	log_print(logger.ERROR, logger.stack_level, string.format(format, ...))
end

return logger

